import type { Request, Response } from 'express';

import config from '@config/index';
import { RepoModel } from '@models/repo';
import { createAppDirectory } from '@routes/app/utils';
import { spawn } from 'child_process';
import { existsSync, statSync } from 'fs';
import { join } from 'path';
import { z } from 'zod';

import Resp from '../../utils/response';

// 参数校验规则
export const validator = z.object({
  // 应用ID，必须是字符串且不能为空
  appId: z.string(),
  // 仓库ID，必须是字符串且不能为空
  repoId: z.string(),
});
// 获取 clone 到本地应用文件夹的 git仓库 的信息
export const api = async (req: Request, res: Response): Promise<Response> => {
  try {
    const { appId, repoId } = req.query as z.infer<typeof validator>;

    // 应用路径
    const appDir = join(config.dataPath, appId);
    // 应用路径是否存在, 如果不存在则创建
    await createAppDirectory(appId);

    // 获取仓库信息
    const repo = await RepoModel.findOne({ _id: repoId });
    if (!repo) {
      return Resp.error(res, 404, '仓库不存在');
    }

    // 仓库路径
    const repoPath = join(appDir, repo.name);
    // 检查仓库路径是否存在 git 仓库(仓库代码是否已 clone 到本地)
    if (!localPathHasGitRepo(repoPath)) {
      return Resp.error(res, 404, '仓库代码未 clone 到本地');
    }

    // 返回成功响应
    return Resp.success(res, 'data', '成功');
  } catch (error) {
    console.error(error);
    // 捕获并处理异常，按错误类型返回合适响应
    return Resp.catch(res, error);
  }
};

/**
 * 检查本地路径是否存在 git 仓库
 * @param dirPath {string} 本地路径
 * @returns {boolean} 是否存在 git 仓库
 */
function localPathHasGitRepo(dirPath: string): boolean {
  const gitPath = join(dirPath, '.git');
  return existsSync(gitPath) && statSync(gitPath).isDirectory();
}

type GitLog = {
  author: string;
  date: string;
  hash: string;
  message: string;
};

/**
 * 获取 git logs 列表，包含分页
 * @param dirPath {string} 本地路径
 * @param page {number} 分页页码
 * @param pageSize {number} 分页大小
 * @returns {GitLog[]} git logs 列表
 */
async function gitInfoList(dirPath: string, page = 1, pageSize = 10): Promise<GitLog[]> {
  return new Promise((resolve, reject) => {
    const gitLogCmd = 'git';
    const gitLogArgs = [
      'log',
      `--pretty=format:%H|%an|%ad|%s`,
      '--date=iso',
      `--skip=${(page - 1) * pageSize}`,
      `--max-count=${pageSize}`,
    ];

    const gitProcess = spawn(gitLogCmd, gitLogArgs, { cwd: dirPath });

    let stdout = '';
    let stderr = '';

    gitProcess.stdout.on('data', data => {
      stdout += data.toString();
    });

    gitProcess.stderr.on('data', data => {
      stderr += data.toString();
    });

    gitProcess.on('close', code => {
      if (code === 0) {
        const logs = stdout
          .split('\n')
          .filter(Boolean)
          .map(line => {
            const [hash, author, date, message] = line.split('|');
            return { author, date, hash, message };
          });
        resolve(logs);
      } else {
        reject(new Error(`git log command failed with code ${code}: ${stderr}`));
      }
    });

    gitProcess.on('error', err => {
      reject(err);
    });
  });
}

/**
 * 获取 git 远程仓库的最新 logs
 * @param url git 仓库地址
 * @param branch 分支
 */
async function gitGitRemoteNewLogs(url: string, branch: string) {}
